from logging.handlers import TimedRotatingFileHandler
import os
import sys
import logging
import inspect
from datetime import datetime
import traceback
from flask import request, has_request_context
import functools

_loggers = {}  # 用于缓存 logger 实例，防止重复配置

def get_logger(name=None, level=logging.INFO) -> logging.Logger:
    if name is None:
        name = "VideoClassifier"

    if name in _loggers:
        return _loggers[name]

    logger = logging.getLogger(name)
    logging.getLogger("uvicorn").setLevel(logging.INFO)
    logging.getLogger("fastapi").setLevel(logging.INFO)
    logging.getLogger("asyncio").setLevel(logging.WARNING)
    logging.getLogger("httpx").setLevel(logging.INFO)
    logger.setLevel(level)

    if not logger.handlers:
        log_directory = os.path.join(os.path.expanduser("~"), "VideoClassifier", "logs")
        os.makedirs(log_directory, exist_ok=True)
        log_file = os.path.join(log_directory, f"{name}_{datetime.now().strftime('%Y-%m-%d')}.log")

        formatter = logging.Formatter(
            fmt='%(asctime)s - %(name)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s',
            datefmt='%Y-%m-%d %H:%M:%S'
        )

        file_handler = TimedRotatingFileHandler(
            log_file,
            when='midnight',     # 每天凌晨切换文件
            interval=1,
            backupCount=30,      # 保留最近 30 天的日志
            encoding='utf-8'
        )
        file_handler.suffix = "%Y-%m-%d"  # 日志文件名加日期
        file_handler.setFormatter(formatter)
        logger.addHandler(file_handler)

        logging.getLogger("sqlalchemy.pool").setLevel(logging.INFO)
        logging.getLogger("ppocr").setLevel(logging.ERROR)
        
        # 添加控制台处理器
        console_handler = logging.StreamHandler(sys.stdout)
        console_handler.setFormatter(formatter)
        console_handler.setLevel(level)
        logger.addHandler(console_handler)
        
    _loggers[name] = logger
    return logger

def _get_request_info():
    """获取当前请求的信息，用于记录在日志中"""
    if not has_request_context():
        return ""
    
    try:
        info = f"[Request: {request.method} {request.path}]"
        # 添加查询参数
        if request.args:
            info += f" Query: {dict(request.args)}"
        # 添加表单数据 (但不包含文件)
        if request.form:
            info += f" Form: {dict(request.form)}"
        # 添加文件信息 (仅显示文件名)
        if request.files:
            files_info = {k: v.filename for k, v in request.files.items()}
            info += f" Files: {files_info}"
        # 添加JSON数据
        if request.is_json:
            try:
                json_data = request.get_json(silent=True)
                if json_data:
                    # 限制JSON数据长度
                    json_str = str(json_data)
                    if len(json_str) > 500:
                        json_str = json_str[:250] + "..." + json_str[-250:]
                    info += f" JSON: {json_str}"
            except:
                pass
        return info
    except:
        return "[无法获取请求信息]"

# 可选：提供函数式调用（贴合 utils 风格）
def log_info(msg, ext=None, highlight=False):
    if highlight:
        colors = ['\033[93m', '\033[92m', '\033[96m', '\033[95m', '\033[94m']
        reset = '\033[0m'
        msg = f"{colors[hash(msg) % len(colors)]}{msg}{reset}"
    logger = get_logger()
    request_info = _get_request_info()
    log_msg = f"{msg} - {ext}" if ext else msg
    if request_info:
        log_msg = f"{log_msg} {request_info}"
    logger.info(log_msg)

def log_error(msg, ext=None, include_stack=True, exc_info=None):
    logger = get_logger()
    request_info = _get_request_info()
    log_message = f"{msg} - {ext}" if ext else msg
    
    if request_info:
        log_message = f"{log_message} {request_info}"
    
    if include_stack:
        if exc_info is not None:
            # 使用传入的异常信息
            logger.error(log_message, exc_info=exc_info)
        else:
            etc_info = sys.exc_info()
            if etc_info[0] is not None:
                # 有活动的异常上下文
                logger.error(log_message, exc_info=True)
            else:
                # 没有活动的异常上下文，收集堆栈
                stack = traceback.format_stack()[:-1]  # 去掉当前调用的栈帧
                stack_str = ''.join(stack)
                logger.error(f"{log_message}\nStack trace:\n{stack_str}")
    else:
        logger.error(log_message)

def log_warning(msg, ext=None):
    logger = get_logger()
    request_info = _get_request_info()
    log_message = f"{msg} - {ext}" if ext else msg
    if request_info:
        log_message = f"{log_message} {request_info}"
    logger.warning(log_message)

def log_debug(msg, ext=None):
    logger = get_logger()
    request_info = _get_request_info()
    log_message = f"{msg} - {ext}" if ext else msg
    if request_info:
        log_message = f"{log_message} {request_info}"
    logger.debug(log_message)

def log_ffmpeg(command, operation, success=True, debug=False):
    """
    记录ffmpeg命令执行情况的专用日志函数
    
    :param command: ffmpeg命令列表
    :param operation: 操作描述
    :param success: 是否成功
    :param debug: 是否记录详细命令(即使成功)
    """
    if success:
        log_info(f"[FFMPEG] {operation} 执行成功")
        if debug:
            # 限制命令长度以避免日志过长
            cmd_str = " ".join(command)
            if len(cmd_str) > 1000:
                cmd_str = cmd_str[:500] + "..." + cmd_str[-500:]
            log_debug(f"[FFMPEG命令] {cmd_str}")
    else:
        log_error(f"[FFMPEG] {operation} 执行失败")
        # 失败时总是记录命令
        cmd_str = " ".join(command)
        if len(cmd_str) > 1000:
            cmd_str = cmd_str[:500] + "..." + cmd_str[-500:]
        log_error(f"[FFMPEG命令] {cmd_str}")

def log_http_exception(e, include_traceback=True):
    """
    专门记录HTTP异常的函数
    
    :param e: HTTP异常对象
    :param include_traceback: 是否包含堆栈跟踪
    """
    status_code = getattr(e, 'code', 500)
    error_name = e.__class__.__name__
    description = getattr(e, 'description', str(e))
    
    log_error(
        f"HTTP Error {status_code} - {error_name}: {description}",
        include_stack=include_traceback,
        exc_info=sys.exc_info() if include_traceback else None
    )
    
def setup_flask_error_handlers(app):
    """
    为Flask应用设置全局异常处理器，确保所有错误都被正确记录
    
    :param app: Flask应用实例
    """
    # 处理HTTP错误
    @app.errorhandler(400)
    def handle_bad_request(e):
        log_http_exception(e)
        return {"error": "Bad Request", "message": str(e)}, 400
    
    @app.errorhandler(404)
    def handle_not_found(e):
        log_http_exception(e)
        return {"error": "Not Found", "message": str(e)}, 404
    
    @app.errorhandler(405)
    def handle_method_not_allowed(e):
        log_http_exception(e)
        return {"error": "Method Not Allowed", "message": str(e)}, 405
    
    @app.errorhandler(500)
    def handle_internal_server_error(e):
        log_http_exception(e)
        return {"error": "Internal Server Error", "message": "服务器内部错误"}, 500
    
    # 处理KeyError（如您的BadRequestKeyError错误）
    @app.errorhandler(KeyError)
    def handle_key_error(e):
        log_error(f"KeyError: 缺少必需的键 '{str(e)}'")
        return {"error": "Bad Request", "message": f"缺少必需的参数: {str(e)}"}, 400
    
    # 处理所有其他异常
    @app.errorhandler(Exception)
    def handle_uncaught_exception(e):
        log_error(f"未捕获的异常: {e.__class__.__name__} - {str(e)}")
        return {"error": "Internal Server Error", "message": "服务器内部错误"}, 500
